package com.anguin.mylibrary.service.impl;

import com.anguin.mylibrary.entity.UserEntity;
import com.anguin.mylibrary.mapper.UserMapper;
import com.anguin.mylibrary.service.UserService;
import com.anguin.mylibrary.service.ex.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.Objects;

import static com.anguin.mylibrary.util.ConstUtil.ENCODE;

/**
 * UserServiceImpl 提供了用户相关的业务逻辑处理，包括用户注册、登录和密码验证。
 * 该服务层与 Mapper 层交互，将数据库操作与业务逻辑分离。
 */
@Service
public class UserServiceImpl implements UserService
{

    // 自动注入 UserMapper，用于与数据库交互
    @Autowired
    private UserMapper userMapper;
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public UserEntity login(String username, String password)
    {
        UserEntity user = userMapper.findByUsername(username);
        if (user == null)
        {
            throw new UserNotFoundException("用户数据不存在");
        }
        if (!validatePassword(password, user.getPassword()))
        {
            throw new PasswordNotMatchException("密码错误");
        }

        if (user.getIsDeleted())
        {
            throw new UserNotFoundException("用户数据不存在");
        }

        UserEntity result = new UserEntity(user.getUserId(), username, user.getGender(), user.getAvatarUrl(), user.getPhoneNumber(), user.getEmail(), user.getSignature());

        return result;
    }

    @Override
    public void register(UserEntity user)
    {
        handleDuplicateException(user);
        user.setPassword(encryptedPassword(user.getPassword()));
        // 设置 BaseEntity 的字段
        user.setCreatedBy(user.getUsername());  // 设置创建者
        user.setIsDeleted(false);
        // 插入用户数据
        Integer raw = userMapper.insertUser(user);
        if (raw != 1)
        {
            throw new InsertException("在用户注册过程中产生了一个未知异常");
        }
    }

    /**
     * 更新用户信息
     *
     * @param user
     */
    @Override
    public UserEntity updateUser(int userId, UserEntity user)
    {
        if (user != null)
        {
            UserEntity result = findByUserId(userId);
            handleDuplicateException(user);
            updateUserIfDifferent(result, user);
            return result;
        }
        throw new UpdateException("更新用户详细信息出错，未知错误");
    }

    /**
     * 处理因为用户的个别信息（如：用户名，手机号，邮箱）重复造成的异常
     *
     * @param user
     */

    private void handleDuplicateException(UserEntity user)
    {
        UserEntity userByUsername = findByUsername(user.getUsername());
        UserEntity userByPhoneNumber = findByPhoneNumber(user.getPhoneNumber());
        UserEntity userByEmail = findByEmail(user.getEmail());
        if (userByUsername != null)
        {
            throw new UsernameDuplicatedException("用户名已被占用");
        }
        if (userByPhoneNumber != null)
        {
            throw new PhoneNumberDuplicatedException("电话号码已被占用");
        }

        if (userByEmail != null)
        {
            System.out.println("抛出 EmailDuplicatedException 异常");
            throw new EmailDuplicatedException("邮箱已被占用");
        }
    }

    @Override
    public void changePassword(int userId, String oldPassword, String newPassword)
    {
        UserEntity user = userMapper.findByUserId(userId);
        System.out.println("changePassword:\n" + user);
        if (user == null)
        {
            throw new UserNotFoundException("用户未找到");
        }
        if (!validatePassword(oldPassword, user.getPassword()))
        {
            throw new PasswordNotMatchException("原密码错误");
        }
        newPassword = encryptedPassword(newPassword);
        int raw = userMapper.changePassword(userId, newPassword);
        System.out.println(raw);
        if (raw != 1)
        {
            throw new UpdateException("用户密码更新出错，未知原因");
        }
    }

    @Override
    public void changePassword(int userId, String newPassword)
    {
        UserEntity user = userMapper.findByUserId(userId);
        System.out.println("changePassword:\n" + user);
        if (user == null)
        {
            throw new UserNotFoundException("用户未找到");
        }
        newPassword = encryptedPassword(newPassword);
        int raw = userMapper.changePassword(userId, newPassword);
        if (raw != 1)
        {
            throw new UpdateException("用户密码更新出错，未知原因");
        }
    }

    @Deprecated
    /**
     * 将 JSON 字符串解析为 UserEntity 对象。
     * @param userJson 包含用户信息的 JSON 字符串
     * @return 返回解析后的 UserEntity 对象
     */
    @Override
    public UserEntity parseUserJson(String userJson)
    {
        try
        {
            return objectMapper.readValue(userJson, UserEntity.class);
        } catch (IOException e)
        {
            throw new RuntimeException("Failed to parse user JSON", e);
        }
    }


    /**
     * 保存用户上传的头像文件。
     * 使用相对路径，将文件保存到项目根目录下的 "uploads" 文件夹。
     * 如果文件夹不存在则会自动创建。
     *
     * @param avatar 用户上传的头像文件
     * @return 返回文件保存的相对路径
     */
    @Override
    public String saveAvatar(MultipartFile avatar)
    {
        try
        {
            String uploadDir = new File("uploads").getAbsolutePath();
            String fileName = avatar.getOriginalFilename();

            File directory = new File(uploadDir);
            if (!directory.exists())
            {
                directory.mkdirs();  // 如果目录不存在，创建该目录
            }

            File destination = new File(uploadDir + File.separator + fileName);
            avatar.transferTo(destination);

            return "uploads" + File.separator + fileName;
        } catch (IOException e)
        {
            throw new RuntimeException("Failed to save avatar", e);
        }
    }

    /**
     * 根据用户名查找用户信息。
     * 通过调用 UserMapper 的 findByUsername 方法从数据库获取用户信息。
     *
     * @param username 用户名
     * @return UserEntity 如果找到用户则返回用户对象，如果找不到则返回 null
     */
    @Override
    public UserEntity findByUsername(String username)
    {
        return userMapper.findByUsername(username);
    }

    /**
     * 注册新用户。
     * 首先对用户的密码进行加密，然后将用户信息存入数据库。
     * 使用 BCryptPasswordEncoder 来对密码进行加密，增强安全性。
     * @param user 包含新用户信息的 UserEntity 对象
     */


    /**
     * 验证用户输入的原始密码与数据库中的加密密码是否匹配。
     * 使用 BCryptPasswordEncoder 的 matches 方法进行验证。
     *
     * @param rawPassword     用户输入的原始密码
     * @param encodedPassword 数据库中存储的加密密码
     * @return 如果密码匹配则返回 true，否则返回 false
     */
    @Override
    public boolean validatePassword(String rawPassword, String encodedPassword)
    {
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        return encoder.matches(rawPassword, encodedPassword);
    }

    public String encryptedPassword(String password)
    {
        return ENCODE.encode(password);
    }

    /**
     * 更新用户的最后登录时间。
     * 调用 UserMapper 的 updateLastLogin 方法，将 last_login 字段设置为当前时间。
     *
     * @param userId 用户的 ID
     */
    @Override
    @Transactional
    public void updateLastLogin(Integer userId)
    {
        int raw = userMapper.updateLastLogin(userId);
        if (raw != 1)
            throw new UpdateException("更新失败，未知错误");
    }

    @Override
    public UserEntity findByEmail(String email)
    {
        return userMapper.findByEmail(email);
    }

    @Override
    public UserEntity findByPhoneNumber(String phoneNumber)
    {
        return userMapper.findByPhoneNumber(phoneNumber);
    }

    @Override
    public UserEntity findByUserId(int uid)
    {
        return userMapper.findByUserId(uid);
    }

    public void updateUserIfDifferent(UserEntity dbUser, UserEntity newUser)
    {
        // 需要更新的标志
        boolean needUpdate = false;

        // 比较 username
        if (newUser.getUsername() != null && !Objects.equals(dbUser.getUsername(), newUser.getUsername()))
        {
            dbUser.setUsername(newUser.getUsername());
            needUpdate = true;
        }

        // 比较 avatarUrl
        if (newUser.getAvatarUrl() != null && !Objects.equals(dbUser.getAvatarUrl(), newUser.getAvatarUrl()))
        {
            dbUser.setAvatarUrl(newUser.getAvatarUrl());
            needUpdate = true;
        }

        // 比较 signature
        if (newUser.getSignature() != null && !Objects.equals(dbUser.getSignature(), newUser.getSignature()))
        {
            dbUser.setSignature(newUser.getSignature());
            needUpdate = true;
        }

        // 比较 gender
        if (newUser.getGender() != null && !Objects.equals(dbUser.getGender(), newUser.getGender()))
        {
            dbUser.setGender(newUser.getGender());
            needUpdate = true;
        }

        // 比较 phoneNumber
        if (newUser.getPhoneNumber() != null && !Objects.equals(dbUser.getPhoneNumber(), newUser.getPhoneNumber()))
        {
            dbUser.setPhoneNumber(newUser.getPhoneNumber());
            needUpdate = true;
        }

        // 比较 email
        if (newUser.getEmail() != null && !Objects.equals(dbUser.getEmail(), newUser.getEmail()))
        {
            dbUser.setEmail(newUser.getEmail());
            needUpdate = true;
        }

        // 如果有需要更新的字段，执行数据库更新操作
        if (needUpdate)
        {
            int raw = userMapper.updateUser(dbUser);
            if (raw != 1)
            {
                throw new UpdateException("用户详细信息更新错误，未知原因");
            }
        }
    }

}
